/**
 * 
 */
package soa.security.dao.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.naming.NamingException;

import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.query.ContainerCriteria;
import org.springframework.ldap.query.LdapQuery;
import org.springframework.ldap.query.LdapQueryBuilder;
import org.springframework.ldap.query.SearchScope;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.stereotype.Repository;

import soa.security.Constants;
import soa.security.dao.DepartmentDao;
import soa.security.dao.impl.OrganizationDaoImpl.OrganizationContextMapper;
import soa.security.domain.Department;
import soa.security.domain.Group;
import soa.security.domain.Organization;
import soa.security.domain.Person;
import soa.security.domain.Position;
import soa.security.domain.Role;

/**
 * @author Cre.Gu
 *
 */
@Repository
public class DepartmentDaoImpl extends SpringLdapDaoImpl<Department> implements
		DepartmentDao {
	@Resource
	private LdapTemplate ldapTemplate;

	@Override
	public void create(Department t) {
		t.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
				.format(new Date()));
		ldapTemplate.create(t);
	}

	@Override
	public Department findByDn(String dn) {
		Department o = ldapTemplate.findByDn(LdapNameBuilder.newInstance(dn)
				.build(), Department.class);
		o.setBid(LdapUtils.getStringValue(o.getDn(), o.getDn().size() - 1));
		o.setOrganization(unitBelongs(dn));
		return o;
	}

	@Override
	public List<Department> allDepartments(String baseDn,
			SearchScope searchScope, Map<String, Object> parameters) {
		ContainerCriteria query = baseQuery(baseDn, searchScope);

		buildLikeCriteria(query, parameters, "name");

		return ldapTemplate.search(query, new BaseContextMapper());
	}

	@Override
	public void addPersons(Department department, Person pe) {
		addAttrName(department.getDn(), "persons", pe.getDn().toString());
	}

	@Override
	public void removePersons(Department department, Person pe) {
		removeAttrName(department.getDn(), "persons", pe.getDn().toString());
	}

	@Override
	public List<String> allPersons(Department department) {
		return allAttrName(department.getDn(), "persons");
	}

	@Override
	public void addPositions(Department department, Position position) {
		addAttrName(department.getDn(), "positions", position.getDn()
				.toString());
	}

	@Override
	public void removePositions(Department department, Position position) {
		removeAttrName(department.getDn(), "positions", position.getDn()
				.toString());
	}

	@Override
	public List<String> allPositions(Department department) {
		return allAttrName(department.getDn(), "positions");
	}

	@Override
	public void addGroups(Department department, Group g) {
		addAttrName(department.getDn(), "groups", g.getDn().toString());
	}

	@Override
	public void removeGroups(Department department, Group g) {
		removeAttrName(department.getDn(), "groups", g.getDn().toString());
	}

	@Override
	public List<String> allGroups(Department department) {
		return allAttrName(department.getDn(), "groups");
	}

	@Override
	public void addRoles(Department department, Role r) {
		addAttrName(department.getDn(), "roles", r.getDn().toString());
	}

	@Override
	public void removeRoles(Department department, Role r) {
		removeAttrName(department.getDn(), "roles", r.getDn().toString());
	}

	@Override
	public List<String> allRoles(Department department) {
		return allAttrName(department.getDn(), "roles");
	}

	public List<Department> allSubDepartments(String baseDn, String parentBid,
			SearchScope searchScope, Map<String, Object> parameters) {
		ContainerCriteria query = baseQuery(baseDn, searchScope);
		query.and("parentBid").is(parentBid);

		buildLikeCriteria(query, parameters, "name");
		return ldapTemplate.search(query, new BaseContextMapper());
	}

	@Override
	public String getObjectClass() {
		return "zjtzsw-department";
	}

	@Override
	public List<String> allApplsystem(Department department) {
		// TODO Auto-generated method stub
		return allAttrName(department.getDn(), "applsystems");
	}
	
	protected class DepartmentContextMapper implements
			ContextMapper<Department> {
		@Override
		public Department mapFromContext(Object ctx) throws NamingException {
			DirContextAdapter context = (DirContextAdapter) ctx;
			return findByDn(context.getDn().toString());
		}
	}

	@Override
	public List<Department> existName(String name) {
		// TODO Auto-generated method stub
		LdapQueryBuilder queryBuilder = LdapQueryBuilder.query();
		LdapQuery query = queryBuilder.searchScope(SearchScope.SUBTREE)
				.where("objectclass").is("zjtzsw-department")
				.and(Constants.DELETED).not().is("TRUE").and("ou").is(name);

		List<Department> dep = ldapTemplate.search(query, new DepartmentContextMapper());
		return dep;
	}

	@Override
	public List<Department> existGradeCode(String gradeCode) {
		// TODO Auto-generated method stub
		LdapQueryBuilder queryBuilder = LdapQueryBuilder.query();
		LdapQuery query = queryBuilder.searchScope(SearchScope.SUBTREE)
				.where("objectclass").is("zjtzsw-department")
				.and(Constants.DELETED).not().is("TRUE").and("gradeCode").is(gradeCode);

		List<Department> dep = ldapTemplate.search(query, new DepartmentContextMapper());
		return dep;
	}
}

